using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using NoMana.Components.Camera;
using SynapseGaming.LightingSystem.Core;
using SynapseGaming.LightingSystem.Rendering;

namespace NoMana.Components.PlayerAvatar
{
    public class UserAvatar : DrawableGameComponent
    {
        bool isInitialized;


        private UserAvatarAction _currentAction;

        private float _scale;

        private Vector3 _currentPosition;
        private Vector3? _targetPosition;
        private double _facing;
        private double _speed;


        public delegate void AvatarArrived();
        public event AvatarArrived OnAvatarArrived;

        private Gamer _owner;

        private SceneInterface _sceneInterface;

        private Avatar _avatar;
        private Guid _nameGuid;

        void LoadGamerAvatar()
        {
            AvatarDescription.BeginGetFromGamer(_owner, GetAvatarCallback, null);

        }

        public void AssignAnimation(IAvatarAnimation animation)
        {
            if (_avatar != null)
            {
                if ((_currentAction == null) || (_currentAction != null && _currentAction.Animation.CurrentPosition >= _currentAction.Animation.Length))
                {
                    _currentAction = new UserAvatarAction(animation, new TimeSpan(0, 0, (int) animation.Length.TotalSeconds));
                    _avatar.SkinBones = _currentAction.Animation.BoneTransforms;
                }
            }
        }

        private Matrix GetSmoothStepAvatarWorldMatrix(GameTime gameTime)
        {
            Matrix currentWorld = Matrix.CreateRotationY(MathHelper.ToRadians(0.0f));

            if (_targetPosition.HasValue)
            {
                if (_currentPosition != _targetPosition.Value)
                {
                    Vector3 movement = Vector3.SmoothStep(_currentPosition, _targetPosition.Value, Convert.ToSingle(_speed));
                    currentWorld *= Matrix.CreateTranslation(movement);
                    _currentPosition = Vector3.Add(_currentPosition, movement);

                    if (Vector3.Distance(movement, _targetPosition.Value) <= 2)
                    {
                        _currentPosition = _targetPosition.Value;
                        _targetPosition = null;
                        //Check if we have reach our position
                        if (OnAvatarArrived != null)
                        {
                            OnAvatarArrived();
                        }
                    }
                }
            }
            else
            {
                currentWorld *= Matrix.CreateTranslation(_currentPosition);
            }

            currentWorld *= Matrix.CreateScale(_scale);

            return currentWorld;


        }


        private Matrix GetAvatarWorldMatrix()
        {
            Matrix currentWorld = Matrix.Identity;

            Vector3 newPostion = _currentPosition;
        
            if (_targetPosition.HasValue)
            {
                newPostion = _targetPosition.Value;
            }

            currentWorld *= Matrix.CreateTranslation(newPostion);

            currentWorld *= Matrix.CreateScale(_scale);

            return currentWorld;
        }


     
        private void GetAvatarCallback(IAsyncResult ar)
        {
            if (ar.IsCompleted)
            {
                if (_avatar == null)
                {
                    AvatarDescription desc = AvatarDescription.EndGetFromGamer(ar);
                    CreateAvatar(desc);
                }
            }
        }

        private void SetupIntialAnimation()
        {
            if (_avatar != null)
            {
                AssignAnimation(new AvatarAnimation(AvatarAnimationPreset.Wave));
            }

            this.Initialize();
        }

        public UserAvatar(Game game, Gamer owner, SceneInterface sceneInterface)
            : base(game)
        {
            _nameGuid = Guid.NewGuid();

            _scale = 1;
            _owner = owner;
            _sceneInterface = sceneInterface;

            LoadGamerAvatar();

        }

        public UserAvatar(Game game, SceneInterface sceneInterface)
            : base(game)
        {
            _nameGuid = Guid.NewGuid();

            _scale = 1;
            _owner = null;
            _sceneInterface = sceneInterface;

            AvatarDescription desc = AvatarDescription.CreateRandom();
            CreateAvatar(desc);

        }

        private void CreateAvatar(AvatarDescription desc)
        {
            AvatarRenderer renderer = new AvatarRenderer(desc, false);

            _avatar = new Avatar(renderer, desc);
            _avatar.World = GetAvatarWorldMatrix();
            _avatar.Visibility = ObjectVisibility.RenderedAndCastShadows;

            _sceneInterface.AvatarManager.Submit(_avatar);
            _sceneInterface.ResourceManager.AssignOwnership(renderer);

            SetupIntialAnimation();
        }

        /// <summary>
        /// Initializes the screen manager component.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();

            isInitialized = true;
        }

        public void SetPostion(Vector3 position)
        {
            _currentPosition = position;

            if (_avatar != null)
            {
                _avatar.World = GetAvatarWorldMatrix();
            }
        }

        public void SetScale(float scale)
        {
            _scale = scale;
        }

        public void SetFacing(double facing)
        {
            _facing = facing;
        }

        public void ChanagePosition(Vector3 targetPostion, double speed)
        {
            _targetPosition = targetPostion;
            _speed = speed;
            if (_avatar != null)
            {
                _avatar.World = GetAvatarWorldMatrix();
            }
        }

        /// <summary>
        /// Load your graphics content.
        /// </summary>
        protected override void LoadContent()
        {
            // Load content belonging to the screen manager.
            ContentManager content = Game.Content;
        }

        /// <summary>
        /// Unload your graphics content.
        /// </summary>
        protected override void UnloadContent()
        {
        }




        public override void Update(GameTime gameTime)
        {
            if(_avatar != null)
            {
                _avatar.Update(gameTime);
            }


            if (isInitialized && _currentAction != null)
            {
                _currentAction.Animation.Update(gameTime.ElapsedGameTime, false);
                base.Update(gameTime);
            }
        }


        public  override void Draw(GameTime gameTime)
        {
           Draw(gameTime, false);
        }

        public void SmoothStepMove(GameTime gameTime)
        {
            //_avatar.World = GetAvatarWorldMatrix(gameTime);
            _avatar.Renderer.World = GetSmoothStepAvatarWorldMatrix(gameTime);
        }

        public void Draw(GameTime gameTime, bool renderInScene)
        {
            if (isInitialized)
            {
                base.Draw(gameTime);

                

                if (!renderInScene)
                {
                    if (_avatar != null)
                    {
                        SmoothStepMove(gameTime);

                        if (_currentAction != null)
                        {
                            _avatar.Renderer.Draw(_currentAction.Animation);
                        }
                        else
                        {
                            _avatar.Renderer.Draw(new AvatarAnimation(AvatarAnimationPreset.Stand0));
                        }
                    }
                }
            }

        }

        protected override void Dispose(bool disposing)
        {
            if(_avatar != null)
            {
                _sceneInterface.AvatarManager.Remove(_avatar);
            }
        }

    }
}